// Web Worker for image restoration
// This worker handles the CPU-intensive task of extracting original images from a stitched image

// Define types for messages
interface WorkerMessage {
  stitchedImageData: {
    width: number;
    height: number;
    data: ArrayBuffer;
  };
  metadata: {
    version: string;
    timestamp: number;
    stitchedImageSize: {
      width: number;
      height: number;
    };
    backgroundColor: string;
    images: Array<{
      id: string;
      name: string;
      x: number;
      y: number;
      width: number;
      height: number;
      format: string;
      rotated?: boolean;
      originalWidth?: number;
      originalHeight?: number;
    }>;
  };
}

interface RestoredImageData {
  id: string;
  name: string;
  width: number;
  height: number;
  format: string;
  imageData: ImageData;
}

/**
 * Extract image data from stitched image data
 * @param stitchedImageData Stitched image data with ArrayBuffer
 * @param x X position
 * @param y Y position
 * @param width Width
 * @param height Height
 * @param stitchedWidth Width of stitched image
 * @returns Extracted image data
 */
function extractImageData(
  stitchedImageData: {
    width: number;
    height: number;
    data: ArrayBuffer;
  },
  x: number,
  y: number,
  width: number,
  height: number,
  stitchedWidth: number
): ImageData {
  // Create new image data
  const imageData = new ImageData(width, height);

  // Convert ArrayBuffer to Uint8ClampedArray for easier access
  const sourceData = new Uint8ClampedArray(stitchedImageData.data);

  // Copy pixel data
  for (let row = 0; row < height; row++) {
    for (let col = 0; col < width; col++) {
      // Calculate positions in source and destination arrays
      const srcPos = ((y + row) * stitchedWidth + (x + col)) * 4;
      const destPos = (row * width + col) * 4;

      // Copy RGBA values
      imageData.data[destPos] = sourceData[srcPos];         // R
      imageData.data[destPos + 1] = sourceData[srcPos + 1]; // G
      imageData.data[destPos + 2] = sourceData[srcPos + 2]; // B
      imageData.data[destPos + 3] = sourceData[srcPos + 3]; // A
    }
  }

  return imageData;
}

// Handle messages from the main thread
self.onmessage = async (e: MessageEvent<WorkerMessage>) => {
  const { stitchedImageData, metadata } = e.data;

  if (!stitchedImageData || !metadata) {
    self.postMessage({
      type: 'error',
      data: { message: '缺少必要的数据' }
    });
    return;
  }

  try {
    // Send initial progress
    self.postMessage({ type: 'progress', data: 0 });

    // Create array for restored images
    const restoredImages: RestoredImageData[] = [];

    // Process each image position from metadata
    const totalImages = metadata.images.length;

    for (let i = 0; i < totalImages; i++) {
      const imagePos = metadata.images[i];

      // Extract image data from stitched image
      const imageData = extractImageData(
        stitchedImageData,
        imagePos.x,
        imagePos.y,
        imagePos.width,
        imagePos.height,
        metadata.stitchedImageSize.width
      );
      
      // 处理旋转的图片
      let finalImageData = imageData;
      let finalWidth = imagePos.width;
      let finalHeight = imagePos.height;
      
      // 如果图片被旋转了，需要将其旋转回原始方向
      if (imagePos.rotated && imagePos.originalWidth && imagePos.originalHeight) {
        // 创建一个新的 ImageData 来存储旋转后的图片
        const rotatedImageData = new ImageData(imagePos.originalWidth, imagePos.originalHeight);
        
        // 旋转图片（逆时针旋转90度，因为在拼接时是顺时针旋转90度）
        for (let y = 0; y < imagePos.height; y++) {
          for (let x = 0; x < imagePos.width; x++) {
            // 源像素位置
            const srcPos = (y * imagePos.width + x) * 4;
            
            // 目标像素位置（逆时针旋转90度）
            // x' = height - 1 - y
            // y' = x
            const destX = imagePos.originalHeight - 1 - y;
            const destY = x;
            const destPos = (destY * imagePos.originalWidth + destX) * 4;
            
            // 复制像素值
            rotatedImageData.data[destPos] = imageData.data[srcPos];         // R
            rotatedImageData.data[destPos + 1] = imageData.data[srcPos + 1]; // G
            rotatedImageData.data[destPos + 2] = imageData.data[srcPos + 2]; // B
            rotatedImageData.data[destPos + 3] = imageData.data[srcPos + 3]; // A
          }
        }
        
        finalImageData = rotatedImageData;
        finalWidth = imagePos.originalWidth;
        finalHeight = imagePos.originalHeight;
      }

      // Create restored image object
      const restoredImage: RestoredImageData = {
        id: imagePos.id,
        name: imagePos.name,
        width: finalWidth,
        height: finalHeight,
        format: imagePos.format,
        imageData: finalImageData
      };

      // Add to restored images array
      restoredImages.push(restoredImage);

      // Update progress
      self.postMessage({
        type: 'progress',
        data: Math.round(((i + 1) / totalImages) * 100)
      });
    }

    // Convert ImageData to transferable format
    const transferableRestoredImages = restoredImages.map(img => {
      // Create a copy of the image data buffer
      const buffer = img.imageData.data.buffer.slice(0);

      return {
        id: img.id,
        name: img.name,
        width: img.width,
        height: img.height,
        format: img.format,
        imageDataBuffer: buffer,
      };
    });

    // Create list of transferable objects
    const transferables = transferableRestoredImages.map(img => img.imageDataBuffer);

    // Send final result with transferable objects
    // Use the correct overload for postMessage with transferables
    // @ts-ignore - TypeScript doesn't recognize the transferables parameter correctly
    self.postMessage({
      type: 'complete',
      data: {
        restoredImages: transferableRestoredImages
      }
    });
  } catch (error: any) {
    self.postMessage({
      type: 'error',
      data: { message: error.message || '还原过程中发生错误' }
    });
  }
};